#pragma once

#include "User.h"
#include "Message_type.h"
#include <sstream>
#include <vector>
#include <ctime>
#include <cstdlib>

#define MIN_PLAYERS 2
#define MAX_PLAYERS 10
#define ROUND_TIME 50
#define SCORES_MAX 10

using namespace std;

void *gameLoopThread(void *);

enum GameState {
	RUN, S_GUESSED, TIMEOUT, INTERRUPTED
};

class Round {
	time_t startTime;	//czas rozpoczecia rundy
	User * winner;
	string pun;			//haslo
	GameState state; // stan rundy

public:
	Round(void) : state(RUN){	startTime = time(NULL);	}

	Round(string pun_) :	pun(pun_), state(RUN) {	startTime = time(NULL);	}

	~Round(void) {}

	/* sprawdza czy dany string jest zgodny z kalamburem */
	bool isPun(string pun_) {	return pun == pun_;	}

	bool isTimeOut() {
		if(time(NULL) - startTime >= ROUND_TIME){
			state=TIMEOUT;
			return true;
		}
		return false;
	}

	string getPun() {	return pun;	}
	GameState getState() {	return state;	}
	void setWinner(User * user) {	winner = user;	}
	User * getWinner() {	return winner;}
	void setState(GameState stan) {	state = stan;}
};

class Game {

	static int counter;

	unsigned int id;	// id gry
	bool started; 		// stan gry, czy rozpoczeta
	int drawerId; 		// id gracza ktory rysuje

	Round * round;		// akutalna runda
	vector<User *> Players;		// vector zawodnikow w danej grze

	vector<string> * Puns;		// adres vectora z haslami

public:

	Game(vector<string> * puns) :	id(++counter), started(false), drawerId(0), Puns(puns) {}

	void start();			// rozpocznij gre
	void gameLoop() ;		// odpal glowna petle gry
	string pickPun();		// wylosuj haslo
	User * findDrawer();	// wyznacz gracza rysujacego

	void updateScores(User * user) {	user->updateScores(2);	}
	void clearScores();

	void sendToAll(int code);
	void sendToAll(int code, string data);
	void sendToAll(int code, char * tab);
	void sendToAllWithoutOne(int code, User *user);
	void sendToAllWithoutOne(int code, char *bufor, User *user);
	void sendToAllWithoutOne(int code, string data, User *user);

	void addPlayer(User *a);
	void removePlayer(User *a);

	User * findPlayerById(int id_);

	//sprawdz czy zgadl haslo
	bool checkIfGuessed(User *user, string pun_);
	int howManyPlayers() {	return Players.size();}

	//czy wygral cala gre
	bool isWinnerOfGame(User * user) {	return user->getScores() >= SCORES_MAX;}
	// czy wystarczajaca liczba gry do startu/kontynuacji rozgrywki
	bool isEnoughPlayersToStart() {		return Players.size() >= MIN_PLAYERS;}
	bool isRoomEmpty() {	return Players.empty();}

	string createRankingMsg();
	string createRoundWinnerMsg(User *user) {	return "Uzytkownik " + user->getLogin() + " odgadl haslo!";}
	string createGameWinnerMsg(User *user) {	return "Uzytkownik " + user->getLogin() + " wygral cala gre!" ;}
	string createYouWinMsg(User *user) {	return "Koniec gry. Wygral uzytkownik " + user->getLogin() + "...";}

	static int getCounter() {	return counter;}
	int getId() {	return id;}
	void setId(int id_) {	id = id_;}
	bool getStarted() {	return started;}
	void setStarted(bool started_) {	started = started_;}


};
